#include <stdarg.h>
#include "xsprintf.h"

#include "kio.h"

unsigned char videobuffer[4000];
// Address to beginning of text mode video ram
// TODO: manage different video modes, or not, since this is kio.c
volatile unsigned char *videoram = (unsigned char *) 0x000B8000;

int caretx = 0;
int carety = 0;
int textcolor = 0x07;

char buf[1024];

void ksettextcolor(int color)
{
	textcolor = (textcolor & 0x000000F0) | (color & 0x0000000F);
}

void ksetbgcolor(int color)
{
	textcolor = (textcolor & 0x0000000F) | ((color << 4) & 0x000000F0);
}

void kscrollpage(void)
{
	int i;
	unsigned short	value;
	
	value = 0xFF00 & (textcolor << 8);
	
	for(i = 0; i < 1920; i++)
	{
		((unsigned short*)videobuffer)[i] = ((unsigned short*)videobuffer)[i + 80];
	}
	for( ; i < 2000; i++)
	{
		((unsigned short*)videobuffer)[i] = value;
	}
	
	// TODO: Use memcpy
	for(i = 0; i < 2000; i++)
		((unsigned short*)videoram)[i] = ((unsigned short*)videobuffer)[i];
}

void kclrscr(void)
{
	unsigned short	value;
	
	value = 0xFF00 & (textcolor << 8);
	
	for(int i = 0; i < 2000; i++)
		((unsigned short*)videoram)[i] =
		((unsigned short*)videobuffer)[i] = value;
}

int kputchar(int c)
{
	int offset;

	switch ((unsigned char)c)
	{
		case '\n':
			caretx = 0;
			carety++;
		break;
		case '\t':
			caretx += 8;
			caretx = caretx & 0xFFFFFFF8;
		break;
		case '\0':
			return 0;
		default:
			offset = carety * 80 + caretx;
			((unsigned short*)videoram)[offset] =
				((unsigned short*)videobuffer)[offset] =
				(unsigned short)(c | (textcolor << 8));
			caretx++;
	}
	
	if(caretx >= 80)
	{
		caretx = 0;
		carety++;
	}
	if(carety >= 25)
	{
		carety = 24;
		kscrollpage();
	}
	
	return c;
}

/*
	Function: kprintf
	Parameters:
	format
		String that contains the text to be written to screen
	additional arguments
		Depending on the format string, the function may expect a sequence of additional arguments.
	Returns: total number of characters written
*/

int kprintf(const char * format, ...)
{
	va_list args;
	int i;

	va_start(args, format);

	xsprintf(buf, format, args);

	for(i = 0; buf[i]; i++)
		kputchar(buf[i]);

	va_end(args);

	return i;
}
